import re
from src.plugins.base import BaseConfig
from lib.conf.config import settings


class Nic(BaseConfig):

    def process(self, command_func, debug):
        if debug:
            with open(settings.BASE_DIR + '/files/nic.out', 'r', encoding='utf-8') as f:
                output = f.read(65535)
            interfaces_info = self.parse(output)
        else:
            output = command_func('ip addr')
            interfaces_info = self.parse(output)
        return interfaces_info

    def parse(self, cmd_data):
        data = self.net_card_classify(cmd_data)
        return self.filter_net_data(data)

    def net_card_classify(self, data):
        """
        对ip addr指令获取的网卡信息进行处理
        :param data: 传入 ip addr 指令获取的数据
        :return: 返回一个数组，其中单个元素就代表某一个网卡的全部信息
        """
        # 将网卡信息进行分割
        a = []
        for i in data.split('<'):
            for j in i.rsplit('\n', 1):
                if not j:
                    continue
                a.append(j)

        # 将网卡信息分配到指定的网卡进行区分，并筛选出真正的网卡
        b = []
        for i in range(len(a)):
            if ': e' in a[i]:
                b.append('<'.join(a[i: i + 2]))
        return b

    def filter_net_data(self, data):
        '''
        对 net_card_classify 处理后的信息进行筛选，获取其中的关键信息
        :param data: net_card_classify的返回值，需要一个数组
        :return: 返回一个字典，包含了筛选出的信息
        '''
        restful = {}
        for i in data:
            mask_data = {
                'status': 'status_none',
                'mac': 'mac_none',
                'ipv4': 'ipv4_none',
                'ipv4_mask': 'ipv4_mask_none',
                'ipv6': 'ipv6_none'
            }
            # 对单个网卡信息中的每项进行筛选
            for j in i.split('\n'):
                net_data = j.strip()
                # 首先获取网卡名称，网卡状态
                if ': e' in net_data:
                    net_name = net_data.split(':')[1].strip()
                    restful[net_name] = mask_data
                    # 获取网卡状态
                    if 'UP' in re.search('<.+>', net_data).group():
                        mask_data['status'] = 'True'
                    else:
                        mask_data['status'] = 'False'

                # 获取网卡mac
                if 'link/' in net_data and 'brd' in net_data:
                    mask_data['mac'] = net_data.split(' ')[1]

                # 获取ipv4地址
                if 'inet' in net_data and 'brd' in net_data:
                    ipaddr_v4, mask_str = net_data.split(' ')[1].split('/')
                    mask_data['ipv4'] = ipaddr_v4

                    # 获取网络掩码 24 --> 255.255.255.0
                    # 根据掩码获取mac地址，例如：24 --> 255.255.255.0
                    mask_data['ipv4_mask'] = self.get_mask(int(mask_str))

                # 获取ipv6地址
                if 'inet6' in net_data and 'scope' in net_data:
                    ipaddr_v6 = net_data.split(' ')[1]
                    mask_data['ipv6'] = ipaddr_v6
        return restful

    def single_mask(self, m=8):
        """
        根据输入的0-8数字，转换为对应的255，例如： 8 --> 255 ，返回string类型
        :param m: 输入 0-8 的 int类型的数字
        :return: 返回转换为string类型的 单个掩码，如：8 --> 255
        """
        binary_array = [128, 64, 32, 16, 8, 4, 2, 1]
        initial_value = 0
        for number_i in range(m):
            initial_value += binary_array[number_i]
        return str(initial_value)

    def get_mask(self, n):
        """
        根据输入的值：0~32, 返回对应的掩码 x.x.x.x
        :param n: 输入int类型， 0 ~ 32 的整数
        :return: 返回整数转换后的掩码，如输入24 --> 255.255.255.0，类型为String
        """
        quotient, remainder = divmod(n, 8)
        initial_mask = ['0', '0', '0', '0']
        for number_j in range(quotient):
            initial_mask[number_j] = self.single_mask()
        initial_mask[quotient] = self.single_mask(remainder)

        return '.'.join(initial_mask)

